package br.edu.ufcg.dsc.services;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.EntityTransaction;

import br.edu.ufcg.dsc.domain.Resource;
import br.edu.ufcg.dsc.domain.ResourceType;
import br.edu.ufcg.dsc.domain.marc.DataField;

public class ResourceService extends BaseService {

	public static void persist(Resource r) {
		EntityTransaction tx = entity.getTransaction();

		tx.begin();
		try {
			if (find(r.getId()) != null) {
				for (DataField d : r.getMarc().getDataFields().values())
					entity.merge(d);
				entity.merge(r.getMarc());
				entity.merge(r);
			} else {
				for (DataField d : r.getMarc().getDataFields().values())
					entity.persist(d);
				entity.persist(r.getMarc());
				entity.persist(r);
			}
			tx.commit();
		} catch (Exception e) {
			e.printStackTrace();
			tx.rollback();
		}
	}

	public static Resource find(int id) {
		return entity.find(Resource.class, id);
	}

	public static List<Resource> findByTitle(String title, ResourceType type) {
		List<Resource> result = new ArrayList<Resource>();
		result.addAll(findByMarc("245", "a", title, type.ordinal()));
		return result;
	}

	public static List<Resource> findByAuthor(String author, ResourceType type) {
		List<Resource> result = new ArrayList<Resource>();

		result.addAll(findByMarc("100", "a", author, type.ordinal()));
		return result;
	}

	public static List<Resource> findByISBN(String isbn, ResourceType type) {
		List<Resource> result = new ArrayList<Resource>();

		result.addAll(findByMarc("020", "a", isbn, type.ordinal()));
		return result;
	}

	public static List<Resource> findByISSN(String issn, ResourceType type) {
		List<Resource> result = new ArrayList<Resource>();

		result.addAll(findByMarc("022", "a", issn, type.ordinal()));
		return result;
	}

	@SuppressWarnings("unchecked")
	public static List<Resource> findByMarc(String field, String subfield,
			String value, int type) {

		List<Integer> idList = entity
				.createNativeQuery(
						"select r.id "
								+ "from resource r, datafield d, datafield_subfields ds, "
								+ "marc_resource mr, marc_resource_datafield mrd "
								+ "where (r.type = :type or :type = :all_type) and r.marc_id = mr.id and mrd.marc_resource_id = mr.id and "
								+ "mrd.datafields_id = d.id and mrd.mapkey like :field and "
								+ "ds.datafield_id = d.id and ds.mapkey like :subfield and "
								+ "upper(ds.element) like :value").setParameter(
						"type", type).setParameter("all_type", ResourceType.ALL.ordinal()).setParameter("field", field + "%")
				.setParameter("subfield", subfield + "%").setParameter("value",
						"%" + value.toUpperCase() + "%").getResultList();

		List<Resource> result = new ArrayList<Resource>();

		for (int id : idList) {
			result.add(find(id));
		}

		return result;
	}
	
	@SuppressWarnings("unchecked")
	public static List<Resource> findAllResources(){
		List<Integer> idList = entity
				.createNativeQuery(
						"select r.id from resource r").getResultList();
		
		List<Resource> result = new ArrayList<Resource>();

		for (int id : idList) {
			result.add(find(id));
		}

		return result;
	}
}
